package com.neusoft.repository.service;

import com.alibaba.fastjson.JSONObject;
import com.neusoft.repository.entity.AddFormEntity;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: repository
 * @description:
 * @author: dong.tl
 * @create: 2019-02-19 18:20
 **/
@Service
public class SolrSerivce {
    @Autowired
    private SolrClient client;

    public Object saveDoc(String fileId, AddFormEntity form) throws IOException, SolrServerException {
        String id = StringUtils.isEmpty(fileId) ? UUID.randomUUID().toString().replaceAll("-", "") : fileId;
        SolrInputDocument doc = new SolrInputDocument();
        doc.setField("id", id);
        doc.setField("title", form.getTitle());
        doc.setField("content", form.getContent());
        doc.setField("user", form.getUser());
        doc.setField("file_id", fileId);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime.now().format(formatter);
        doc.setField("create_time", LocalDateTime.now().format(formatter));
        client.add(doc);
        client.commit();
        return null;
    }

    private final static String[] HighlightField = new String[]{"title", "content", "user"};

    /**
     * 综合查询: 在综合查询中, 有按条件查询, 条件过滤, 排序, 分页, 高亮显示, 获取部分域信息
     *
     * @return
     */
    @RequestMapping("/search")
    @ResponseBody
    public Map<String, Object> search(String search_text, int page, int count) throws IOException, SolrServerException {
        boolean isHighlight = false;
        Map req = new HashMap();
        SolrQuery params = new SolrQuery();
        //查询条件
        params.set("q", StringUtils.isEmpty(search_text) ? "*:*" : escapeQueryChars(search_text));

//            //过滤条件
//            params.set("fq", "product_price:[100 TO 100000]");

        //排序
        if (StringUtils.isEmpty(search_text))
            params.addSort("create_time", SolrQuery.ORDER.desc);

        //分页
        page = page - 1 <= 0 ? 0 : page - 1;
        count = count <= 0 ? 10 : count;
        params.setStart(page * count);
        params.setRows(count);

        //默认域
        params.set("df", "search_all");

        //只查询指定域
//            params.set("fl", "id,title,content,user");

        //高亮
        //打开开关
        params.setHighlight(true);
        //指定高亮域
        params.addHighlightField(Arrays.stream(HighlightField).collect(Collectors.joining(",")));
        //设置前缀
        params.setHighlightSimplePre("<span style='color:red'>");
        //设置后缀
        params.setHighlightSimplePost("</span>");

        QueryResponse queryResponse = client.query(params);

        SolrDocumentList results = queryResponse.getResults();

        long numFound = results.getNumFound();

        req.put("numFound", numFound);
        req.put("totalPages", (numFound + count - 1) / count);

        //获取高亮显示的结果, 高亮显示的结果和查询结果是分开放的
        Map<String, Map<String, List<String>>> highlight = queryResponse.getHighlighting();

        List data = new ArrayList();
        for (SolrDocument result : results) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("id", result.get("id").toString());
            jsonObject.put("user", result.get("user") == null ? " - " : result.get("user").toString());
            jsonObject.put("title", result.get("title") == null ? "" : result.get("title").toString());
            jsonObject.put("content", result.get("content") == null ? "" : result.get("content").toString());
            Calendar ca = Calendar.getInstance();
            ca.setTime((Date) result.get("create_time"));
            ca.add(Calendar.HOUR_OF_DAY, -8);
            jsonObject.put("createTime", DateFormatUtils.format(ca.getTime(), "yyyy-MM-dd HH:mm:ss"));
            jsonObject.put("fileId", result.get("file_id") == null ? "" : result.get("file_id").toString());

            Map<String, List<String>> map = highlight.get(result.get("id"));
            if (!map.isEmpty()) {
                for (String field : HighlightField) {
                    List<String> list = map.get(field);
                    if (list != null && !list.isEmpty()) {
                        if (field.equals("content"))
                            jsonObject.put("highlight_" + field, list.get(0)+"...");
                        else
                            jsonObject.put(field, list.get(0));
                    }
                }
            }

            data.add(jsonObject);

        }
        req.put("data", data);
        return req;

    }


    public String delete(String id) throws IOException, SolrServerException {
        client.deleteById(id);
        client.commit();
        return id;
    }


    public static String escapeQueryChars(String s) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            // These characters are part of the query syntax and must be escaped
            if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':'
                    || c == '^' || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' || c == '~'
                    || c == '*' || c == '?' || c == '|' || c == '&' || c == ';' || c == '/'
                    || Character.isWhitespace(c)) {
                sb.append('\\');
            }
            sb.append(c);
        }
        return sb.toString();
    }
}
